package com.glsc.ngateway.platform.service.gitee;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.dto.PageQueryParamDto;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.utils.CommonUtils;
import com.glsc.ngateway.common.api.common.utils.DateUtil;
import com.glsc.ngateway.common.api.common.utils.JsonUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.flowable.dto.CreatedTaskInfoDto;
import com.glsc.ngateway.common.api.flowable.dto.CurrentTaskInfoDto;
import com.glsc.ngateway.common.api.flowable.dto.demand.*;
import com.glsc.ngateway.common.api.flowable.feign.IFeignFlowableService;
import com.glsc.ngateway.common.api.flowable.resp.FlowableResponse;
import com.glsc.ngateway.common.api.flowable.resp.ResponseSituationDto;
import com.glsc.ngateway.common.api.platform.dto.gitee.*;
import com.glsc.ngateway.common.api.platform.dto.gitee.issueBase.IssueFileDto;
import com.glsc.ngateway.common.api.shortmsg.bo.MessageGenericVo;
import com.glsc.ngateway.common.api.shortmsg.feign.IFeignShortmsgService;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.SystemConfig;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.Appendix;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.gitee.GiteeSyncLog;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.gitee.IssueBase;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.SystemMain;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.AppendixRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.GiteeSyncLogRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.IssueBaseRepo;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.controller.dev.DemandManagementController;
import com.glsc.ngateway.platform.domain.DevTaskChangeLog;
import com.glsc.ngateway.platform.domain.FlowFormDevManage;
import com.glsc.ngateway.platform.domain.FlowFormTaskDetail;
import com.glsc.ngateway.platform.dto.GiteeDataBaseDto;
import com.glsc.ngateway.platform.dto.GiteeDataBaseOutDto;
import com.glsc.ngateway.platform.dto.GiteeProgramDto;
import com.glsc.ngateway.platform.dto.GiteeProgramOutDto;
import com.glsc.ngateway.platform.repo.DevManageRepository;
import com.glsc.ngateway.platform.repo.DevTaskChangeLogRepository;
import com.glsc.ngateway.platform.repo.DevTaskDetailRepository;
import com.glsc.ngateway.platform.service.MailService;
import com.glsc.ngateway.platform.service.SystemConfigService;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.it.DictionaryService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.glsc.ngateway.common.api.common.enums.PlatformConstant.*;

/**
 * @author zhengyr
 * @date 2024/1/23-10:51
 * 获取gitee任务相关
 */
@Service
public class GiteeNewService {
    private static final Logger logger = LoggerFactory.getLogger(GiteeNewService.class);
    private static final String timeZoneFormatter = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
    private static final String[] closeStateIdArray = {"10", "18", "11", "12", "13"}; //已完成，已取消，已拒绝，已关闭,已验收 的任务状态
    private static final Map<Integer, String> programMap = ImmutableMap.of(34, "国联技术服务平台",17, "资管产品系统",35, "资管直销柜台客户服务平台");

    @Value("${gitee.enterprise_id}")
    public String enterpriseId;

    @Value("${gitee.url}")
    public String baseUrl;

    @Value("${gitee.url_user}")
    public String giteeUserUrl;

    @Value("${gitee.access_token}")
    public String accessToken;

    @Resource
    private RestTemplate restTemplate;
    @Resource
    private IFeignFlowableService feignDemandService;
    @Resource
    private SystemMainService systemMainService;
    @Resource
    private AppendixRepo appendixRepo;
    @Resource
    private GiteeSyncLogRepo giteeSyncLogRepo;
    @Resource
    private DevManageRepository devManageRepository;
    @Resource
    private DevTaskDetailRepository devTaskDetailRepository;
    @Resource
    private DemandManagementController managementController;
    @Resource
    private IssueBaseRepo issueBaseRepo;
    @Resource
    private DictionaryService dictionaryService;
    @Resource
    private MailService mailService;
    @Resource
    private UserCache userCache;
    @Resource
    private DevTaskChangeLogRepository devTaskChangeLogRepository;
    @Resource
    private UserService userService;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private IFeignShortmsgService iFeignShortmsgService;
    @Value("${wechat.url}")
    private String weChatUrl;


    //    @Scheduled(cron = "0 0 8,18 * * ?")
    public void syncAllIssueScheduled() {
        logger.info("开始同步Gitee任务");
        syncAllIssue(LocalDate.now().minusDays(1));
    }

    private ExecutorService demandPool = Executors.newCachedThreadPool();

    /**
     * 同步所有Gitee任务至网关。
     * @param date 用于筛选问题的创建日期，仅同步大于该日期的问题。如果为null，则清空当前所有问题数据并重新同步所有问题。
     */
    public synchronized void syncAllIssue(LocalDate date) {
        int pageSize = 100;
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "issues")
                .queryParam("per_page", pageSize)
                .queryParam("access_token", accessToken);
        if (Objects.nonNull(date)) {
            uriBuilder.queryParam("created_at", ">" + date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "T00:00:00.000+08:00");
        } else {
            issueBaseRepo.truncate();
        }
        for (int i = 1; ; i++) {
            String uriString = cn.hutool.core.net.URLDecoder.decode(uriBuilder
                    .queryParam("page", i)
                    .toUriString(), StandardCharsets.UTF_8);
            ResponseEntity<IssueOutDto> resp = restTemplate.getForEntity(uriString, IssueOutDto.class);
            IssueOutDto issueInfo = resp.getBody();
            if (null == issueInfo || issueInfo.getTotal_count() == 0 || CollectionUtil.isEmpty(issueInfo.getData())) {
                logger.info("同步Gitee工作项{}: 同步结束, total:{}", Objects.nonNull(date) ? date : "All", Objects.isNull(issueInfo) ? "接口返回为null" : issueInfo.getTotal_count());
                break;
            }
            List<IssueBase> domainList = issueInfo.getData().stream()
                    .map(dto -> IssueBase.builder()
                            .id(dto.getId())
                            .root_id(dto.getRoot_id())
                            .parent_id(dto.getParent_id())
                            .program_id(dto.getProgram_id())
                            .program_name(systemMainService.findNameByGiteeId(dto.getProgram_id()))
                            .ident(dto.getIdent())
                            .title(dto.getTitle())
                            .issue_state_id(dto.getIssue_state_id())
                            .state(dto.getState())
                            .priority(dto.getPriority())
                            .priority_human(dto.getPriority_human())
                            .assignee(Objects.isNull(dto.getAssignee()) ? null : dto.getAssignee().getUsername())
                            .issue_types(dto.getIssue_type().getTitle())
                            .collaborators(CollectionUtils.isEmpty(dto.getCollaborators()) ? null : dto.getCollaborators().stream().map(GiteeMemberDto::getUsername).collect(Collectors.joining(",")))
                            .plan_started_at(dto.getPlan_started_at())
                            .deadline(dto.getDeadline())
                            .started_at(dto.getStarted_at())
                            .finished_at(dto.getFinished_at())
                            .created_at(dto.getCreated_at())
                            .updated_at(dto.getUpdated_at())
                            .overDays(dto.getOverDays())
                            .build())
                    .collect(Collectors.toList());
            issueBaseRepo.saveAll(domainList);
            logger.info("同步Gitee工作项All: 成功, pageNum-{}, pageSize-{}, 共{}个", i, pageSize, issueInfo.getTotal_count());
        }
    }

    /**
     * 需求模块任务与Gitee同步。
     *
     */
    public void syncGiteeIssue() {
        List<GiteeSyncLog> proIssue = giteeSyncLogRepo.findAllByProcessDefKeyAndTaskDefKeyAndStatusNotIn(
                "DemandManagement", "arrangeTask", List.of("已验收", "已拒绝", "异常或已删除"));
        Map<String, List<OnlineTaskReq>> onlineParamMap = new HashMap<>();
        Set<String> unFinishProcessIdSet = new HashSet<>();
        proIssue.stream()
                .collect(Collectors.groupingBy(GiteeSyncLog::getProcessId))
                .entrySet()
                .forEach(entry -> {
                    String processId = entry.getKey();
                    entry.getValue().forEach(log -> {
                        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "issues/" + log.getGiteeIssueId())
                                .queryParam("access_token", accessToken)
                                .toUriString();
                        try {
                            ResponseEntity<IssueBaseDto> resp = restTemplate.getForEntity(uriString, IssueBaseDto.class);
                            IssueBaseDto issueInfo = resp.getBody();
                            if ((HttpStatus.OK).equals(resp.getStatusCode()) && Objects.nonNull(issueInfo)) {
                                String status = issueInfo.getIssue_state().getTitle();
                                log.setStatus(status);
                                switch (status) {
                                    case "已完成":
                                    case "已验收":
                                        onlineParamMap.compute(processId, (proId, paramList) -> {
                                            ZonedDateTime defaultTime = ZonedDateTime.of(2024,02,01,00,00,00,00,ZoneId.systemDefault());
                                            paramList = CollectionUtils.isEmpty(paramList) ? new ArrayList<>() : paramList;
                                            paramList.add(OnlineTaskReq.builder()
                                                    .rqId(processId)
                                                    .taskId(log.getTaskId())
                                                    .onlineinfo(OnlineInf.builder()
                                                            .actualOnlineDate(StrUtil.isEmpty(issueInfo.getFinished_at()) ? defaultTime.toLocalDate() : ZonedDateTime.parse(issueInfo.getFinished_at()).toLocalDate())
                                                            .devUserId(issueInfo.getAssignee().getUsername())
                                                            .endDevDate(StrUtil.isEmpty(issueInfo.getDeadline()) ? defaultTime.toLocalDate() : ZonedDateTime.parse(issueInfo.getDeadline()).toLocalDate())
                                                            .startDevDate(StrUtil.isEmpty(issueInfo.getPlan_started_at()) ? defaultTime.toLocalDate() : ZonedDateTime.parse(issueInfo.getPlan_started_at()).toLocalDate())
                                                            .build())
                                                    .commnet("Gitee端同步")
                                                    .build());
                                            return paramList;
                                        });
                                        break;
                                    //TODO: 拒绝情况
                                    default:
                                        log.setStatus(status);
                                        unFinishProcessIdSet.add(processId);
                                }
                            }
                        } catch (HttpClientErrorException e) {
                            logger.error("Gitee获取任务详情失败{}", e.getMessage());
                            log.setStatus("异常或已删除");
                        }
                    });
                });
        if (!onlineParamMap.isEmpty()) {
            onlineParamMap.forEach((proId, paramList) -> {
                paramList.forEach(param -> {
                    managementController.onlineTask(null, param);
                    logger.info("Gitee同步需求{}", param);
                });
                if (!unFinishProcessIdSet.contains(proId)) {
                    List<GiteeSyncLog> demandLogs = giteeSyncLogRepo.findAllByProcessIdAndGiteeIssueType(proId, "需求");
                    demandLogs.forEach(log -> {
                        try {
                            HttpHeaders headers = new HttpHeaders();
                            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                            Map<String, Object> requestBody = new HashMap<>();
                            requestBody.put("access_token", accessToken);
                            requestBody.put("issue_state_id", 10);
                            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
                            restTemplate.put(baseUrl+enterpriseId+"/" + "issues/" + log.getGiteeIssueId(), requestEntity);
                            log.setStatus("已完成");
                            proIssue.add(log);
                        } catch (HttpClientErrorException e) {
                            logger.error("Gitee修改需求状态失败:{}", e.getMessage());
                        }
                    });
                }
            });
            giteeSyncLogRepo.saveAll(proIssue);
        } else {
            logger.info("Gitee无任务同步");
        }
    }

    @Cacheable(cacheNames = "getGiteeUserId#600")
    public String getGiteeUserId(@NotBlank String account) throws UnsupportedEncodingException {
        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "members")
                .queryParam("access_token", accessToken)
                .queryParam("search", account)
                .toUriString();
        ResponseEntity<GiteeMemberOutDto> resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeMemberOutDto.class);
        if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
            logger.error("Gitee同步失败：获取成员{" + account + "}失败:" + resp);
            return null;
        }
        List<GiteeMemberDto> memberOutDtoList = resp.getBody().getData().stream().filter(person -> StrUtil.equals(person.getUsername(),account)).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(memberOutDtoList)){
            mailService.sendMailToAdmin(account+"在gitee中不存在",account+"在gitee中不存在");
            return null;
        }
        return memberOutDtoList.get(0).getId();
    }

    @Cacheable(cacheNames = "getGiteePrograms#600")
    public String getGiteePrograms(@NotBlank String name) throws UnsupportedEncodingException {
        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "programs")
                .queryParam("access_token", accessToken)
                .queryParam("enterprise_id",enterpriseId)
                .queryParam("per_page",100)
                .toUriString();
        ResponseEntity<GiteeProgramOutDto> resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeProgramOutDto.class);
        if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
            logger.error("Gitee同步失败：获取成员失败:" + resp);
            return null;
        }
        List<GiteeProgramDto> programs = resp.getBody().getData();
        Optional<GiteeProgramDto> program = programs.stream().filter(e -> StrUtil.equals(e.getName(), name)).findFirst();
        if (program.get() == null){
            return null;
        }
        return program.get().getId();
    }

    @Cacheable(cacheNames = "getDataBaseList#600")
    public List<GiteeDataBaseDto> getDataBaseList() throws UnsupportedEncodingException {
        int perPageSize = 100;
        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "projects")
                .queryParam("access_token", accessToken)
//                .queryParam("enterprise_id",enterpriseId)
                .queryParam("per_page",perPageSize)
                .toUriString();
        ResponseEntity<GiteeDataBaseOutDto> resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
        if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
            logger.error("Gitee同步失败：获取成员失败:" + resp);
            return null;
        }
        List<GiteeDataBaseDto> all = new ArrayList<>();
        List<GiteeDataBaseDto> programs = resp.getBody().getData();
        all.addAll(programs);
        int total = resp.getBody().getTotal_count();
        double pageNum = Math.ceil((double) total/perPageSize);
        int nowPage = 1;
        while (--pageNum >0){
            uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "projects")
                    .queryParam("access_token", accessToken)
                    .queryParam("page",String.valueOf(++nowPage))
                    .queryParam("per_page",perPageSize)
                    .toUriString();
            resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
            if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
                logger.error("Gitee同步失败：获取成员失败:" + resp);
                return null;
            }
            all.addAll(resp.getBody().getData());
        }
        return all;
    }

    public void addGiteeDemand(FlowFormDevManage flowFormDevManage) throws UnsupportedEncodingException {
        if (StrUtil.isNotEmpty(flowFormDevManage.getGiteeIssueId())){
            return;
        }
        SystemMain systemMain = systemMainService.findBySystemClassNo(flowFormDevManage.getSystemCode());
        String sysid = getGiteePrograms(systemMain.getOpName());
        if (Strings.isBlank(sysid)) {
            logger.error("Gitee添加需求失败：未找到项目sysid-{}", flowFormDevManage.getSystemName());
            mailService.sendMailToAdmin("gitee创建需求异常","Gitee添加需求失败：未找到项目sysid-"+flowFormDevManage.getSystemName());
            return;
        }
        LocalDateTime startTime = flowFormDevManage.getProcessCreateTime();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("access_token", accessToken);
//            requestBody.put("title", startTime.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-" + processInfo[0].getProcessTitle() + "-From" + processInfo[0].getStartUserChineseName());
//            requestBody.put("title", startTime.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-"
//                    + Optional.ofNullable(dictionaryService.findByDictEntryAndDictSubentry("demand_type", demandInfo.getDemandType()))
//                    .map(d -> "【" + d.getDictValue() + "】").orElse("") + "-"
//                    + processInfo[0].getProcessTitle() + "-From" + processInfo[0].getStartUserChineseName());
        requestBody.put("title",flowFormDevManage.getDemandTitle());
        requestBody.put("description",
                "<div><strong><h3>需求背景</h3><strong></div>"
                        + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandBackground()) ? flowFormDevManage.getDemandBackground() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求目标</h3><strong></div>"
                        + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandPurpose()) ? flowFormDevManage.getDemandPurpose() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求来源</h3><strong></div>"
                        + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandFrom()) ? flowFormDevManage.getDemandFrom() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求关联方</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandRelateAccount()) ? userCache.get(flowFormDevManage.getDemandRelateAccount()).getName() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求概述</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandSummary()) ? flowFormDevManage.getDemandSummary() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求边界</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandBoundary()) ? flowFormDevManage.getDemandBoundary() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求风险</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandRisk()) ? flowFormDevManage.getDemandRisk() : Strings.EMPTY) + "</div>"+
                "<div><strong><h3>需求详述</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandDetail()) ? flowFormDevManage.getDemandDetail() : Strings.EMPTY) + "</div>"
                + "<div><strong><h3>解决方案</h3><strong></div>"
                + "<div>" + (Strings.isNotBlank(flowFormDevManage.getDemandSolution()) ? flowFormDevManage.getDemandSolution() : Strings.EMPTY) + "</div>"
        );
        requestBody.put("assignee_id",  getGiteeUserId(flowFormDevManage.getSystemAdminAccount()));
        //需求
        requestBody.put("issue_type_id", "3");
        requestBody.put("program_id", sysid);
        requestBody.put("plan_started_at", ZonedDateTime.of(startTime, ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern("E MMM dd HH:mm:ss zzz yyyy", Locale.US)));
        requestBody.put("priority", Objects.isNull(flowFormDevManage.getDemandPriority()) ? "0":flowFormDevManage.getDemandPriority());
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
        logger.info("qinqiudemand"+requestEntity);
        ResponseEntity<IssueBaseDto> giteeResp = restTemplate.postForEntity(baseUrl+enterpriseId+"/" + "issues", requestEntity, IssueBaseDto.class);
        if ((HttpStatus.OK).equals(giteeResp.getStatusCode()) || (HttpStatus.CREATED).equals(giteeResp.getStatusCode())) {
            IssueBaseDto issueBaseDto = giteeResp.getBody();
            flowFormDevManage.setGiteeIssueId(String.valueOf(issueBaseDto.getId()));
            devManageRepository.save(flowFormDevManage);
            List<Appendix> docDtoList = new ArrayList<>();
            //需求文档
            if (flowFormDevManage != null && StrUtil.isNotBlank(flowFormDevManage.getDemandDocIdList())) {
                String[] docIds = flowFormDevManage.getDemandDocIdList().split(",");
                if (docIds != null && docIds.length > 0) {
                    for (String docId : docIds) {
                        Appendix appendix = appendixRepo.findById(docId);
                        docDtoList.add(appendix);
                    }
                }
            }
            //设计文档
            if (flowFormDevManage != null && StrUtil.isNotBlank(flowFormDevManage.getDemandDesignDocIdList())) {
                String[] docIds = flowFormDevManage.getDemandDesignDocIdList().split(",");
                List<Appendix> docList = new ArrayList<>();
                if (docIds != null && docIds.length > 0) {
                    for (String docId : docIds) {
                        Appendix appendix = appendixRepo.findById(docId);
                        docDtoList.add(appendix);
                    }
                }
            }
            uploadFile(docDtoList,issueBaseDto);
        }
    }

    private void uploadFile(List<Appendix> docDtoList, IssueBaseDto issueBaseDto) {
        //上传附件
        if (CollectionUtil.isEmpty(docDtoList)) {
            logger.info("需求无文档，无需创建");
            return;
        }
        List<File> docFiles = Collections.emptyList();
        try {
            CountDownLatch lock = new CountDownLatch(docDtoList.size());
            logger.info("需求文档共{}个，开始创建", docDtoList.size());
//                    MultipartEntityBuilder
            UUID uuid = UUID.randomUUID();
            docFiles = docDtoList.parallelStream()
                    .map(doc -> {
                        byte[] body = feignDemandService.oaDownloadAppendix(doc.getAppendixId()).getBody();
                        String annexName = StrUtil.isEmpty(doc.getAppendixName()) ? "附件":doc.getAppendixName();
                        File tempFile = null;
                        FileOutputStream fos = null;
                        try {
                            tempFile = new File(uuid + "/" + annexName);
                            tempFile.getParentFile().mkdirs(); // 如果父目录不存在，则创建
                            tempFile.createNewFile();
                            fos = new FileOutputStream(tempFile);
                            fos.write(body);
                            fos.flush();
                            if(Objects.nonNull(fos)) {
                                fos.close();
                            }
                            logger.info("下载附件成功：", annexName);
                        } catch (IOException e) {
                            logger.error("下载附件失败：", e.getMessage());
                        } finally {
                            lock.countDown();
//                                    tempFile.delete();
//                                    return new FileSystemResource(tempFile);
                        }
                        return tempFile;
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            try {
                lock.await();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
            logger.info("需求文档共{}个，创建完成，下载结果{}个", docDtoList.size(), docFiles.size());
            if (CollectionUtils.isEmpty(docFiles)) {
                return;
            }
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
            MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
            formData.add("attach_type", "issue");
            formData.add("attach_id", String.valueOf(issueBaseDto.getId()));
            HttpEntity<MultiValueMap<String, Object>> requestEntity2 = new HttpEntity<>(formData, headers);
            docFiles.forEach(doc -> {
                formData.remove("file");
                formData.add("file", new FileSystemResource(doc));
                ResponseEntity<String> docResp = restTemplate.postForEntity(baseUrl+enterpriseId+"/" + "attach_files/upload?access_token=" + accessToken, requestEntity2, String.class);
                logger.info("需求管理，文档上传:{}, resp:{}", doc, docResp);
            });
            logger.info("需求文档共{}个，全部上传完毕", docFiles.size());
        } finally {
            if (CollectionUtils.isNotEmpty(docFiles)) {
                File parent = docFiles.get(0).getParentFile();
                docFiles.forEach(File::delete);
                parent.delete();
            }
        }
    }

    public void addGiteeTask(FlowFormDevManage giteeDemandDto) throws UnsupportedEncodingException {
        //过滤掉taskid空的
        List<FlowFormTaskDetail> taskList = giteeDemandDto.getDetail().stream()
                .filter(t->StrUtil.isEmpty(t.getGiteeTaskId()) && !StrUtil.equals(giteeDemandDto.getGiteeIssueId(),"-1")).collect(Collectors.toList());

//        taskList = taskList.stream().filter(e -> StrUtil.isEmpty(e.getGiteeTaskId())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(taskList)){
            SystemMain systemMain = systemMainService.findBySystemClassNo(giteeDemandDto.getSystemCode());
            String sysid = getGiteePrograms(systemMain.getOpName());
            if (Strings.isBlank(sysid)) {
                logger.error("Gitee添加需求失败：未找到项目sysid-{}", giteeDemandDto.getSystemName());
                mailService.sendMailToAdmin("gitee创建需求异常","Gitee添加需求失败：未找到项目sysid-"+giteeDemandDto.getSystemName());
                return;
            }
            for (FlowFormTaskDetail task : taskList) {
                try {
                    String giteeUserId = getGiteeUserId(task.getTaskPersonAccount());
                    String giteeDemandId = giteeDemandDto.getGiteeIssueId();
                    LocalDateTime startTime = task.getPlanDateBegin().atStartOfDay();
                    LocalDateTime ddl = task.getPlanDate().atStartOfDay();
                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
                    Map<String, Object> requestBody = new HashMap<>();
                    requestBody.put("access_token", accessToken);
                    requestBody.put("title", startTime.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-"
                            + task.getTaskTitle() );
                    requestBody.put("description",
                            "<div><strong><h3>任务描述</h3><strong></div>"
                                    + "<div>" + (Strings.isNotBlank(task.getTaskContent()) ? task.getTaskContent() : Strings.EMPTY) + "</div>"
                    );
                    requestBody.put("assignee_id", giteeUserId);
                    //任务
                    requestBody.put("issue_type_id", "2");
                    requestBody.put("program_id", sysid);
                    requestBody.put("plan_started_at", ZonedDateTime.of(startTime, ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern("E MMM dd HH:mm:ss zzz yyyy", Locale.US)));
                    requestBody.put("deadline", ZonedDateTime.of(ddl, ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ofPattern("E MMM dd HH:mm:ss zzz yyyy", Locale.US)));
                    requestBody.put("priority", Objects.isNull(giteeDemandDto.getDemandPriority() ) ? 0 : Integer.valueOf(giteeDemandDto.getDemandPriority()));
                    requestBody.put("link_issue_id", giteeDemandId);
                    requestBody.put("link_ref_type", "normal");
                    requestBody.put("link_direction", "none");
                    HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
                    logger.info("qinqiutask"+requestEntity);
                    ResponseEntity<IssueBaseDto> giteeResp = restTemplate.postForEntity(baseUrl+enterpriseId+"/" + "issues", requestEntity, IssueBaseDto.class);
                    if ((HttpStatus.OK).equals(giteeResp.getStatusCode()) || (HttpStatus.CREATED).equals(giteeResp.getStatusCode())) {
                        IssueBaseDto issueBaseDto = giteeResp.getBody();
                        task.setGiteeIdent(issueBaseDto.getIdent());
                        task.setGiteeUrl(giteeUserUrl+sysid+"/tasks/table?issue="+issueBaseDto.getIdent());
                        task.setGiteeTaskId(String.valueOf(issueBaseDto.getId()));
                        devTaskDetailRepository.save(task);
                        DevTaskChangeLog taskLog = new DevTaskChangeLog();
                        taskLog.setLogFlag(DictConstant.ADD);
                        taskLog.setRelateType(TASK_MANAGE_LOG_TYPE);
                        taskLog.setRelateId(task.getTaskId().toString());
                        taskLog.setLogJson(JSONObject.toJSONString(task));
                        taskLog.setOpOperator("系统同步");
                        taskLog.setOpOperatorName("系统同步");
                        taskLog.setStatus("已创建gitee任务");
                        task.getDetailLog().add(taskLog);
                        devTaskChangeLogRepository.save(taskLog);
                        notify("Gitee已自动创建开发任务", task.getTaskTitle()+":"+task.getTaskContent(), List.of(task.getTaskPersonAccount()));
                    }
                } catch (UnsupportedEncodingException e) {
                    logger.error("Gitee创建任务失败, {}", task, e);
                }
            }
        }
    }

    public void notify(@NotNull String title,String content, List<String> notifyAccount) {
        String[] mailList = userService.findAllByAccountList(notifyAccount).stream().map(User::getEmail).toArray(String[]::new);;
        SystemConfig agentIdConfig = systemConfigService.findByCode("WECHAT_GATEWAY_APP_AGENTID");
        boolean hasAgentIdConfig = Objects.nonNull(agentIdConfig) && Strings.isNotBlank(agentIdConfig.getConfigValue());
        //邮件通知
//        String title = String.format("【需求流程】-【节点审核】-【%s】", formDevManage.getProcessTitle());
//        String content = String.format("需求标题：%s<br/>  发起人：%s<br/>  需求系统：%s<br/>  负责人：%s<br/>  需求概要：%s<br/>  请知悉。可至国联技术服务平台内查阅相关事宜。"
//                , formDevManage.getDemandTitle()
//                , formDevManage.getFlowCreateOperatorName()
//                , Optional.ofNullable(systemMainService.findBySystemClassNo(formDevManage.getSystemCode()))
//                        .orElseThrow(() -> PlatformException.error("未找到系统：" + formDevManage.getSystemCode())).getOpName()
//                , userCache.get(formDevManage.getSystemAdminAccount()).getName()
////                , (Objects.isNull(formDevManage.getEventGrade()) ? "无" :
////                        Optional.ofNullable(dictionaryService.findByDictEntryAndDictSubentry("event_manage_grade", formDevManage.getEventGrade()))
////                                .orElseThrow(() -> PlatformException.error("未找到字典项：event_manage_grade， " + formDevManage.getEventGrade())).getDictValue())
////                , (Objects.isNull(formDevManage.getEventClass()) ? "无" :
////                        Optional.ofNullable(dictionaryService.findByDictEntryAndDictSubentry("event_manage_class", formDevManage.getEventClass()))
////                                .orElseThrow(() -> PlatformException.error("未找到字典项：event_manage_class， " + formDevManage.getEventClass())).getDictValue())
//                , formDevManage.getDemandSummary() != null && formDevManage.getDemandSummary().length() > 500 ? formDevManage.getDemandSummary().substring(0, 500) + "..." : formDevManage.getDemandSummary()
//        );
        mailService.sendMail(mailList, null, title
                ,  DictConstant.ISSUE_LINK
                , title, content, null, Constant.MAIL_TYPE_IT_FLOW
        );
        if (hasAgentIdConfig) {
            iFeignShortmsgService.sendAgentMessageGeneric(MessageGenericVo.builder()
                    .oaUserAccounts(notifyAccount)
                    .agentId(agentIdConfig.getConfigValue())
                    .textContent("<br><a href='" + weChatUrl + "'>" + title + "</a>" +
                            "<br>  " + content)
                    .build());
        }
    }


    @Transactional
    public void syncGiteeState(FlowFormDevManage devManage) {
        //过滤掉taskid空的
        List<FlowFormTaskDetail> details = devManage.getDetail().stream().filter(t->StrUtil.isNotEmpty(t.getGiteeTaskId())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(details)){
            for ( FlowFormTaskDetail detail : details){
                String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl +enterpriseId+"/"+ "issues/" + detail.getGiteeTaskId())
                        .queryParam("access_token", accessToken)
                        .toUriString();
                try {
                    logger.info("requeststate"+uriString);
                    ResponseEntity<IssueBaseDto> resp = restTemplate.getForEntity(uriString, IssueBaseDto.class);
                    IssueBaseDto issueInfo = resp.getBody();
                    if ((HttpStatus.OK).equals(resp.getStatusCode()) && Objects.nonNull(issueInfo)) {
                        String status = issueInfo.getIssue_state().getTitle();
                        logger.info("returnstate"+status);
                        detail.setGiteeOrignalState(status);
                        String lastStatus = detail.getDetailLog().get(0).getStatus();
                        //状态不一致加日志
                        if (!lastStatus.equals(status)){
                            if (lastStatus.equals(TASK_MANAGE_LOG_STATUS_WAIT) && status.equals("待办的")){
                                //初始状态不用同步
                            } else {
                                DevTaskChangeLog taskLog = new DevTaskChangeLog();
                                taskLog.setLogFlag(DictConstant.ADD);
                                taskLog.setRelateType(TASK_MANAGE_LOG_TYPE);
                                taskLog.setRelateId(detail.getTaskId().toString());
                                taskLog.setLogJson(JSONObject.toJSONString(status));
                                taskLog.setOpOperator("系统同步");
                                taskLog.setOpOperatorName("系统同步");
                                taskLog.setStatus(status);
                                detail.getDetailLog().add(taskLog);
                                devTaskChangeLogRepository.save(taskLog);
                            }
                        }
                        switch (status) {
                            case "待办的":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_WAIT);
                                break;
                            case "已确认":
                                break;
                            case "进行中":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_DOING);
                                break;
                            case "测试中":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_TESTING);
                                break;
//                            case "已测试":
//                                break;
                            case "已完成":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_DONE);
                                detail.setFinishDate(StrUtil.isEmpty(issueInfo.getFinished_at()) ? LocalDate.now() : ZonedDateTime.parse(issueInfo.getFinished_at()).toLocalDate());
                                break;
//                            case "已关闭":
//                                break;
                            case "已验收":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_DONE);
                                detail.setFinishDate(StrUtil.isEmpty(issueInfo.getFinished_at()) ? LocalDate.now() : ZonedDateTime.parse(issueInfo.getFinished_at()).toLocalDate());
                                break;
                            case "已拒绝":
                                detail.setTaskState(TASK_MANAGE_LOG_STATUS_REJECT);
                                break;
                            default:
                        }
                    }
                } catch (HttpClientErrorException e) {
                    logger.error("Gitee获取任务详情失败{}", e.getMessage());
//                    log.setStatus("异常或已删除");
                }
            }
            devManageRepository.save(devManage);
        }
    }

    public void createBranch(FlowFormTaskDetail detail) {
        try {
            String branchName = "feature-"+detail.getTaskPersonAccount()+"-"+LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))+"-"+detail.getGiteeIdent()+"-"+detail.getTaskTitle();
            String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "projects/"+detail.getGiteeDataBaseId()+"/branches")
                                .toUriString();
            logger.info("createBranch"+uriString);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("access_token", accessToken);
            requestBody.put("branch_name", branchName);
            requestBody.put("refs","master");
            requestBody.put("action","new");
            requestBody.put("type", 0);
            requestBody.put("remark", "系统自动创建");
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
            ResponseEntity<JSONObject> postForEntity = restTemplate.postForEntity(uriString, requestEntity, JSONObject.class);

            if ((HttpStatus.CREATED).equals(postForEntity.getStatusCode())) {
                detail.setGiteeDataBaseBranchStatus(DictConstant.YES_1);
                devTaskDetailRepository.save(detail);
                DevTaskChangeLog taskLog = new DevTaskChangeLog();
                taskLog.setLogFlag(DictConstant.ADD);
                taskLog.setRelateType(TASK_MANAGE_LOG_TYPE);
                taskLog.setRelateId(detail.getTaskId().toString());
                taskLog.setLogJson(JSONObject.toJSONString(detail));
                taskLog.setOpOperator("系统同步");
                taskLog.setOpOperatorName("系统同步");
                taskLog.setStatus("已创建分支");
                detail.getDetailLog().add(taskLog);
                devTaskChangeLogRepository.save(taskLog);
                notify("Gitee已自动创建开发分支", "分支名称："+branchName, List.of(detail.getTaskPersonAccount()));
            } else{
                mailService.sendMailToAdmin("创建分支失败",postForEntity.getBody().toString());
            }
            logger.info("gittee queryMemberList请求失败。方法返回原始报文:" + postForEntity.getBody());
        } catch (Exception e) {
            logger.error("gitee接口queryMemberList异常:", e);
            throw PlatformException.error("gitee接口queryMemberList异常");
        }
    }

    public List<GiteeDataBaseDto> getProgramDataBaseList(String systemName) throws UnsupportedEncodingException {
        String sysid = getGiteePrograms(systemName);
        int perPageSize = 100;
        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "programs/"+sysid+"/projects")
                .queryParam("access_token", accessToken)
//                .queryParam("enterprise_id",enterpriseId)
                .queryParam("per_page",perPageSize)
                .toUriString();
        ResponseEntity<GiteeDataBaseOutDto> resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
        if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
            logger.error("Gitee同步失败：获取成员失败:" + resp);
            return null;
        }
        List<GiteeDataBaseDto> all = new ArrayList<>();
        List<GiteeDataBaseDto> programs = resp.getBody().getData();
        all.addAll(programs);
        int total = resp.getBody().getTotal_count();
        double pageNum = Math.ceil((double) total/perPageSize);
        int nowPage = 1;
        while (--pageNum >0){
            uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "programs/"+sysid+"/projects")
                    .queryParam("access_token", accessToken)
                    .queryParam("page",String.valueOf(++nowPage))
                    .queryParam("per_page",perPageSize)
                    .toUriString();
            resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
            if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
                logger.error("Gitee同步失败：获取成员失败:" + resp);
                return null;
            }
            all.addAll(resp.getBody().getData());
        }
        return all;
    }

    public List<GiteeDataBaseDto> getDataBaseBranchList(String dataBaseId) throws UnsupportedEncodingException {
        int perPageSize = 100;
        String uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "projects/"+dataBaseId+"/branches")
                .queryParam("access_token", accessToken)
//                .queryParam("enterprise_id",enterpriseId)
                .queryParam("per_page",perPageSize)
                .toUriString();
        ResponseEntity<GiteeDataBaseOutDto> resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
        if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
            logger.error("Gitee同步失败：获取成员失败:" + resp);
            return null;
        }
        List<GiteeDataBaseDto> all = new ArrayList<>();
        List<GiteeDataBaseDto> programs = resp.getBody().getData();
        all.addAll(programs);
        int total = resp.getBody().getTotal_count();
        double pageNum = Math.ceil((double) total/perPageSize);
        int nowPage = 1;
        while (--pageNum >0){
            uriString = UriComponentsBuilder.fromHttpUrl(baseUrl+enterpriseId+"/" + "projects/"+dataBaseId+"/branches")
                    .queryParam("access_token", accessToken)
                    .queryParam("page",String.valueOf(++nowPage))
                    .queryParam("per_page",perPageSize)
                    .toUriString();
            resp = restTemplate.getForEntity(URLDecoder.decode(uriString, "UTF-8"), GiteeDataBaseOutDto.class);
            if (!(HttpStatus.OK).equals(resp.getStatusCode()) || CollectionUtil.isEmpty(resp.getBody().getData())) {
                logger.error("Gitee同步失败：获取成员失败:" + resp);
                return null;
            }
            all.addAll(resp.getBody().getData());
        }
        return all;
    }
}
